package com.lineage.server.datatables.sql;

import com.lineage.DatabaseFactory;
import com.lineage.server.IdFactory;
import com.lineage.server.model.Instance.L1PcInstance;
import com.lineage.server.templates.L1Mail;
import com.lineage.server.utils.PerformanceTimer;
import com.lineage.server.utils.SQLUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Iterator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class MailTable {
  private static final Log _log = LogFactory.getLog(MailTable.class);
  
  private static MailTable _instance;
  
  private static ArrayList<L1Mail> _allMail = new ArrayList<>();
  
  public static MailTable get() {
    if (_instance == null)
      _instance = new MailTable(); 
    return _instance;
  }
  
  public void load() {
    PerformanceTimer timer = new PerformanceTimer();
    Connection con = null;
    PreparedStatement pstm = null;
    ResultSet rs = null;
    try {
      con = DatabaseFactory.get().getConnection();
      pstm = con.prepareStatement("SELECT * FROM character_mails");
      rs = pstm.executeQuery();
      while (rs.next()) {
        L1Mail mail = new L1Mail();
        mail.setId(rs.getInt("id"));
        mail.setType(rs.getInt("type"));
        mail.setSenderName(rs.getString("sender"));
        mail.setReceiverName(rs.getString("receiver"));
        mail.setDate(rs.getTimestamp("date"));
        mail.setReadStatus(rs.getInt("read_status"));
        mail.setInBoxId(rs.getInt("inbox_id"));
        mail.setSubject(rs.getBytes("subject"));
        mail.setContent(rs.getBytes("content"));
        _allMail.add(mail);
      } 
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(rs);
      SQLUtil.close(pstm);
      SQLUtil.close(con);
    } 
    _log.info("载入信件资料数量: " + _allMail.size() + "(" + timer.get() + "ms)");
  }
  
  public void setReadStatus(int mailId) {
    Connection con = null;
    PreparedStatement pstm = null;
    ResultSet rs = null;
    try {
      con = DatabaseFactory.get().getConnection();
      pstm = con.prepareStatement("UPDATE character_mails SET read_status=? WHERE id=?");
      pstm.setInt(1, 1);
      pstm.setInt(2, mailId);
      pstm.execute();
      changeMailStatus(mailId);
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(rs);
      SQLUtil.close(pstm);
      SQLUtil.close(con);
    } 
  }
  
  public void setMailType(int mailId, int type) {
    Connection con = null;
    PreparedStatement pstm = null;
    ResultSet rs = null;
    try {
      con = DatabaseFactory.get().getConnection();
      pstm = con.prepareStatement("UPDATE character_mails SET type=? WHERE id=?");
      pstm.setInt(1, type);
      pstm.setInt(2, mailId);
      pstm.execute();
      changeMailType(mailId, type);
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(rs);
      SQLUtil.close(pstm);
      SQLUtil.close(con);
    } 
  }
  
  public void deleteMail(int mailId) {
    Connection con = null;
    PreparedStatement pstm = null;
    try {
      con = DatabaseFactory.get().getConnection();
      pstm = con.prepareStatement("DELETE FROM character_mails WHERE id=?");
      pstm.setInt(1, mailId);
      pstm.execute();
      delMail(mailId);
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(pstm);
      SQLUtil.close(con);
    } 
  }
  
  public int writeMail(int type, String receiver, L1PcInstance writer, byte[] text, int inboxId) {
    Timestamp date = new Timestamp(System.currentTimeMillis());
    int readStatus = 0;
    int id = 0;
    int spacePosition1 = 0;
    int spacePosition2 = 0;
    int i = 0;
    while (i < text.length) {
      if (text[i] == 0 && text[i + 1] == 0)
        if (spacePosition1 == 0) {
          spacePosition1 = i;
        } else if (spacePosition1 != 0 && spacePosition2 == 0) {
          spacePosition2 = i;
          break;
        }  
      i += 2;
    } 
    int subjectLength = spacePosition1 + 2;
    int contentLength = spacePosition2 - spacePosition1;
    if (contentLength <= 0)
      contentLength = 1; 
    byte[] subject = new byte[subjectLength];
    byte[] content = new byte[contentLength];
    System.arraycopy(text, 0, subject, 0, subjectLength);
    System.arraycopy(text, subjectLength, content, 0, contentLength);
    Connection con = null;
    PreparedStatement pstm2 = null;
    try {
      con = DatabaseFactory.get().getConnection();
      pstm2 = con.prepareStatement(
          "INSERT INTO character_mails SET id=?, type=?, sender=?, receiver=?, date=?, read_status=?, inbox_id=?, subject=?, content=?");
      id = IdFactory.get().nextId();
      pstm2.setInt(1, id);
      pstm2.setInt(2, type);
      pstm2.setString(3, writer.getName());
      pstm2.setString(4, receiver);
      pstm2.setTimestamp(5, date);
      pstm2.setInt(6, 0);
      pstm2.setInt(7, inboxId);
      pstm2.setBytes(8, subject);
      pstm2.setBytes(9, content);
      pstm2.execute();
      L1Mail mail = new L1Mail();
      mail.setId(id);
      mail.setType(type);
      mail.setSenderName(writer.getName());
      mail.setReceiverName(receiver);
      mail.setDate(date);
      mail.setReadStatus(0);
      mail.setInBoxId(inboxId);
      mail.setSubject(subject);
      mail.setContent(content);
      _allMail.add(mail);
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(pstm2);
      SQLUtil.close(con);
    } 
    return id;
  }
  
  public ArrayList<L1Mail> getAllMail() {
    return _allMail;
  }
  
  public L1Mail getMail(int mailId) {
    Iterator<L1Mail> iterator = _allMail.iterator();
    while (iterator.hasNext()) {
      L1Mail mail = iterator.next();
      if (mail.getId() == mailId)
        return mail; 
    } 
    return null;
  }
  
  private void changeMailStatus(int mailId) {
    Iterator<L1Mail> iterator = _allMail.iterator();
    while (iterator.hasNext()) {
      L1Mail mail = iterator.next();
      if (mail.getId() == mailId) {
        L1Mail newMail = mail;
        newMail.setReadStatus(1);
        _allMail.remove(mail);
        _allMail.add(newMail);
        break;
      } 
    } 
  }
  
  private void changeMailType(int mailId, int type) {
    Iterator<L1Mail> iterator = _allMail.iterator();
    while (iterator.hasNext()) {
      L1Mail mail = iterator.next();
      if (mail.getId() == mailId) {
        L1Mail newMail = mail;
        newMail.setType(type);
        _allMail.remove(mail);
        _allMail.add(newMail);
        break;
      } 
    } 
  }
  
  private void delMail(int mailId) {
    Iterator<L1Mail> iterator = _allMail.iterator();
    while (iterator.hasNext()) {
      L1Mail mail = iterator.next();
      if (mail.getId() == mailId) {
        _allMail.remove(mail);
        break;
      } 
    } 
  }
}
